/*
 * @(#)Locker.java        3.0.0   2018年01月02日 上午8:21:29
 *
 * Copyright (c) 2007-2017 A cable international early education，Xi'an，China.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of Asuo
 * ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Asuo.
 */
package com.mvc.core.utils;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @ClassName: Locker
 * @Description: 锁类
 * @author 杨志华
 * @date: 2018年01月02日 上午08:26:29
 * @version: 3.0.0
 */
public class Locker {
	/**
	 * @Fields LOGGER : 日志
	 */
	private static final Logger LOGGER = LoggerFactory.getLogger(Locker.class);
	/**
	 * @Fields DEFAULT_LOCK : 默认锁
	 */
	private static ReadWriteLock DEFAULT_LOCK = new ReentrantReadWriteLock();
	private static Map<Object, ReadWriteLock> CONTEXT_KEY_LOCK = new ConcurrentHashMap<Object, ReadWriteLock>();

	public static Lock readLock(Object key) {
		return getLock(key).readLock();
	}

	public static Lock writeLock(Object key) {
		return getLock(key).writeLock();
	}

	public static void lock(Lock lock) {
		try {
			lock.lock();
		} catch (Exception e) {
			LOGGER.warn("lock failure.", e);
		}
	}

	public static void tryLock(Lock lock) {
		try {
			boolean t = lock.tryLock();
			if (!t) {
				LOGGER.warn("tryLock", t);
			}
		} catch (Exception e) {
			LOGGER.warn("tryLock failure.", e);
		}
	}

	public static void unlock(Lock lock) {
		try {
			lock.unlock();
		} catch (Exception e) {
			LOGGER.warn("unlock failure.", e);
		}
	}

	public static void lockInterruptibly(Lock lock) {
		try {
			lock.lockInterruptibly();
		} catch (Exception e) {
			LOGGER.warn("lockInterruptibly failure.", e);
		}
	}

	private static ReadWriteLock getLock(Object key) {
		if (key == null) {
			return DEFAULT_LOCK;
		}
		return CONTEXT_KEY_LOCK.putIfAbsent(key, new ReentrantReadWriteLock());
	}
}
